/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.client.area.plot;

import nl.cloudfarming.client.area.plot.pref.AreaCulturePreference;
import com.vividsolutions.jts.geom.MultiPolygon;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import nl.cloudfarming.client.area.AreaService;
import nl.cloudfarming.client.geoviewer.Layer;
import nl.cloudfarming.client.geoviewer.LayerProvider;
import nl.cloudfarming.client.model.Culture;
import nl.cloudfarming.client.model.Plot;
import nl.cloudfarming.client.model.PlotFile;
import nl.cloudfarming.client.util.MD5Sum;
import nl.cloudfarming.client.util.ShapeFileCopier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.geotools.data.FeatureSource;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.opengis.feature.simple.SimpleFeature;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;

/**
 *
 * @author Timon Veenstra
 */
public class ShapeFileProcessor {

    private final File shapeFile;
    private final AreaService areaService = new PlotAreaService();
    ShapeFileCopier fileCopier = new ShapeFileCopier();
    ArrayList<File> shapeList = new ArrayList<File>();
    private static Log log = LogFactory.getLog(ShapeFileProcessor.class);

//                    InputOutput io = IOProvider.getDefault().getIO("Task", true);
//                    io.getOut().println("Info message");
//                    io.getErr().println("error message");
//                    io.getOut().close();
//                    io.getErr().close();
    public ShapeFileProcessor(File shapeFile) {
        this.shapeFile = shapeFile;
    }

    public void process() {
        ShapefileDataStore shpDataStore = null;
        if (shapeFile.isFile()) {
            try {
                String checkSum = MD5Sum.getHex(MD5Sum.createChecksum(new FileInputStream(shapeFile)));
                PlotFile plotFile = new PlotFile();
                plotFile.setChecksum(checkSum);
                plotFile.setFileCreated(new Date(shapeFile.lastModified()));
                plotFile.setFileName(shapeFile.getName());
                plotFile.setFileRead(new Date());


                if (areaService.findPlotFileByNameChecksum(shapeFile.getName(), checkSum) == null) {
                    areaService.persist(plotFile);

                    shpDataStore = new ShapefileDataStore(shapeFile.toURI().toURL());
                    String typeName = shpDataStore.getTypeNames()[0];
                    // TODO: next call generates 2 exceptions
                    //- sun.misc.ServiceConfigurationError: org.opengis.filter.expression.Function: Provider org.geotools.filter.function.math.FilterFunction_toRadians not found
                    //- sun.misc.ServiceConfigurationError: org.geotools.feature.FeatureTypeFactory: Provider org.geotools.feature.DefaultFeatureTypeFactory not found
                    FeatureSource featureSource = shpDataStore.getFeatureSource(typeName);
                    FeatureCollection result = featureSource.getFeatures();
                    FeatureIterator itertor = result.features();
                    while (itertor.hasNext()) {
                        SimpleFeature feature = (SimpleFeature) itertor.next();
                        Plot plot = null;
                        if (Boolean.valueOf(AreaCulturePreference.SHAPE_CONTAINTS_PLOT.getValue())){
                            plot = parsePlot(feature, plotFile);
                            areaService.persist(plot);
                        }

                        Culture culture = null;
                        
                        if (Boolean.valueOf(AreaCulturePreference.SHAPE_CONTAINTS_CULTURE.getValue())){
                            culture = parseCulture(feature, plotFile,plot);
                            if (plot == null){
                                areaService.persist(culture.getPlot());
                            }
                            areaService.persist(culture);
                        }
                        
                        
                    }
                    itertor.close();
                    //FIXME hack to update layers loading of sensor data needs refactoring to simpler architecture
                    for (LayerProvider provider : Lookup.getDefault().lookupAll(LayerProvider.class)) {
                        if (provider instanceof PlotLayerProvider) {
                            for (Layer layer : ((PlotLayerProvider) provider).getLookup().lookupAll(Layer.class)) {
                                layer.updateLayer();
                            }
                        }
                    }

                } else {
                    StringBuilder sb = new StringBuilder("The shape File: ");
                    sb.append(shapeFile.getName());
                    sb.append("Is already loaded");
                    log.info(sb);
                }
//                StringBuilder sb = new StringBuilder((shapeFile).getParent());
                //Get copy to directory from netbeans propperties
//                File loadFile = new File(AreaCulturePreference.SHAPE_FILE_ARCHIVE_DIR.getValue());
//                fileCopier.moveFile(shapeFile, loadFile, true);
            } catch (NoSuchAlgorithmException ex) {
                Exceptions.printStackTrace(ex);
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }
//    private static final String ATTRIBUTENAME_POLYGON = "the_geom";
//    private static final String ATTRIBUTENAME_PLOTNAME = "KAVEL";
//    private static final String ATTRIBUTENAME_TEELT_NR = "TEELT_NR";
//    private static final String ATTRIBUTENAME_GEWAS = "GEWAS";
//    private static final String ATTRIBUTENAME_RAS = "RAS";
//    private static final String ATTRIBUTENAME_OPER_HA = "OPER_HA";

    private Plot parsePlot(SimpleFeature payload, PlotFile plotFile) {
        int attIndexPlotPoly = payload.getFeatureType().indexOf(AreaCulturePreference.SHAPE_ATT_POLYGON.getValue());
        int attIndexPlotName = payload.getFeatureType().indexOf(AreaCulturePreference.SHAPE_ATT_NAME.getValue());
        MultiPolygon shape = null;
        if (attIndexPlotPoly >= 0) {
            shape = (MultiPolygon) payload.getAttribute(attIndexPlotPoly);
        }
        String plotName = "Onbekend";
        if (attIndexPlotName >= 0) {
            plotName = (String) payload.getAttribute(attIndexPlotName);
        }

        Plot plot = new Plot();
        plot.setName(plotName);
        plot.setPlotFile(plotFile);
        plot.setWKT(shape.toString());

        return plot;
    }

    private Culture parseCulture(SimpleFeature payload, PlotFile plotFile, Plot plot) {
        int attIndexPlotPoly = payload.getFeatureType().indexOf(AreaCulturePreference.SHAPE_ATT_POLYGON.getValue());
        int attIndexPlotName = payload.getFeatureType().indexOf(AreaCulturePreference.SHAPE_ATT_NAME.getValue());
        MultiPolygon shape = null;
        if (attIndexPlotPoly >= 0) {
            shape = (MultiPolygon) payload.getAttribute(attIndexPlotPoly);
        }
        String plotName = "Onbekend";
        if (attIndexPlotName >= 0) {
            plotName = (String) payload.getAttribute(attIndexPlotName);
        }

        // create a plot similar to the culture
        if (plot == null) {
            plot = new Plot();
            plot.setName(plotName);
            plot.setPlotFile(plotFile);
            plot.setWKT(shape.toString());
        }

        Culture culture = new Culture();
        culture.setName(plotName);
        culture.setPlotFile(plotFile);
        culture.setPlot(plot);
        culture.setWKT(shape.toString());
        culture.setStartDate(new Date());

        return culture;
    }
}
